<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Testing OAuth 2.0 :: Spring Security</title>
<link rel="canonical" href="../../../../reactive/test/web/oauth2.html">
<link rel="prev" href="csrf.html">
<link rel="next" href="../../configuration/webflux.html">
<meta name="generator" content="Antora 3.0.0">
<link rel="stylesheet" href="../../../../_/css/site.css">
<link href="../../../../_/img/favicon.ico" rel='shortcut icon' type='image/vnd.microsoft.icon'>
<link rel="stylesheet" href="../../../../_/css/vendor/docsearch.min.css">

<script>var uiRootPath = '../../../../_'</script>
</head>
<body class="article">
<header class="header">
<nav class="navbar">
<div class="navbar-brand">
<a class="navbar-item" href="https://spring.io">
<img id="springlogo" class="block" src="../../../../_/img/spring-logo.svg" alt="Spring">
</a>
<button class="navbar-burger" data-target="topbar-nav">
<span></span>
<span></span>
<span></span>
</button>
</div>
<div id="topbar-nav" class="navbar-menu">
<div class="navbar-end">
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="oauth2.html#">Why Spring</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="https://spring.io/why-spring">Overview</a>
<a class="navbar-item" href="https://spring.io/microservices">Microservices</a>
<a class="navbar-item" href="https://spring.io/reactive">Reactive</a>
<a class="navbar-item" href="https://spring.io/event-driven">Event Driven</a>
<a class="navbar-item" href="https://spring.io/cloud">Cloud</a>
<a class="navbar-item" href="https://spring.io/web-applications">Web Applications</a>
<a class="navbar-item" href="https://spring.io/serverless">Serverless</a>
<a class="navbar-item" href="https://spring.io/batch">Batch</a>
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="oauth2.html#">Learn</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="https://spring.io/learn">Overview</a>
<a class="navbar-item" href="https://spring.io/quickstart">Quickstart</a>
<a class="navbar-item" href="https://spring.io/guides">Guides</a>
<a class="navbar-item" href="https://spring.io/blog">Blog</a>
</div>
</div>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="oauth2.html#">Projects</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="https://spring.io/projects">Overview</a>
<a class="navbar-item" href="https://spring.io/projects/spring-boot">Spring Boot</a>
<a class="navbar-item" href="https://spring.io/projects/spring-framework">Spring Framework</a>
<a class="navbar-item" href="https://spring.io/projects/spring-cloud">Spring Cloud</a>
<a class="navbar-item" href="https://spring.io/projects/spring-cloud-dataflow">Spring Cloud Data Flow</a>
<a class="navbar-item" href="https://spring.io/projects/spring-data">Spring Data</a>
<a class="navbar-item" href="https://spring.io/projects/spring-integration">Spring Integration</a>
<a class="navbar-item" href="https://spring.io/projects/spring-batch">Spring Batch</a>
<a class="navbar-item" href="https://spring.io/projects/spring-security">Spring Security</a>
<a class="navbar-item navbar-item-special" href="https://spring.io/projects">View all projects</a>
<a class="navbar-item" href="https://spring.io/tools">Spring Tools 4</a>
<a class="navbar-item navbar-item-special-2" href="https://start.spring.io">Spring Initializr <svg class="external-link-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><polyline points="15 10.94 15 15 1 15 1 1 5.06 1" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="2"></polyline><polyline points="8.93 1 15 1 15 7.07" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="2"></polyline><line x1="15" y1="1" x2="8" y2="8" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="2"></line></svg></a>
</div>
</div>
<a class="navbar-item" href="https://spring.io/training">Training</a>
<a class="navbar-item" href="https://spring.io/support">Support</a>
<div class="navbar-item has-dropdown is-hoverable is-community">
<a class="navbar-link" href="oauth2.html#">Community</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="https://spring.io/community">Overview</a>
<a class="navbar-item" href="https://spring.io/events">Events</a>
<a class="navbar-item" href="https://spring.io/team">Team</a>
</div>
</div>
</div>
</div>
<div id="switch-theme">
<input type="checkbox" id="switch-theme-checkbox" />
<label for="switch-theme-checkbox">Dark Theme</label>
</div>
</nav>
</header>
<div class="body">
<div class="nav-container" data-component="ROOT" data-version="5.6.0">
<aside class="nav">
<div class="panels">
<div class="nav-panel-menu is-active" data-panel="menu">
<nav class="nav-menu">
<h3 class="title"><a href="../../../index.html">Spring Security</a></h3>
<ul class="nav-list">
<li class="nav-item" data-depth="0">
<ul class="nav-list">
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../../index.html">Overview</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../../prerequisites.html">Prerequisites</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../../community.html">Community</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../../whats-new.html">What&#8217;s New</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../../getting-spring-security.html">Getting Spring Security</a>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../features/index.html">Features</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../features/authentication/index.html">Authentication</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../features/authentication/password-storage.html">Password Storage</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../features/exploits/index.html">Protection Against Exploits</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../features/exploits/csrf.html">CSRF</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../features/exploits/headers.html">HTTP Headers</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../features/exploits/http.html">HTTP Requests</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../features/integrations/index.html">Integrations</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../features/integrations/cryptography.html">Cryptography</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../features/integrations/data.html">Spring Data</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../features/integrations/concurrency.html">Java&#8217;s Concurrency APIs</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../features/integrations/jackson.html">Jackson</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../features/integrations/localization.html">Localization</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../../modules.html">Project Modules</a>
</li>
<li class="nav-item" data-depth="1">
<a class="nav-link" href="../../../samples.html">Samples</a>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/index.html">Servlet Applications</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../../../servlet/getting-started.html">Getting Started</a>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../../../servlet/architecture.html">Architecture</a>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/authentication/index.html">Authentication</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authentication/architecture.html">Authentication Architecture</a>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/authentication/passwords/index.html">Username/Password</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/authentication/passwords/input.html">Reading Username/Password</a>
<ul class="nav-list">
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../../../servlet/authentication/passwords/form.html">Form</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../../../servlet/authentication/passwords/basic.html">Basic</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../../../servlet/authentication/passwords/digest.html">Digest</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="4">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/authentication/passwords/storage.html">Password Storage</a>
<ul class="nav-list">
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../../../servlet/authentication/passwords/in-memory.html">In Memory</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../../../servlet/authentication/passwords/jdbc.html">JDBC</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../../../servlet/authentication/passwords/user-details.html">UserDetails</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../../../servlet/authentication/passwords/user-details-service.html">UserDetailsService</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../../../servlet/authentication/passwords/password-encoder.html">PasswordEncoder</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../../../servlet/authentication/passwords/dao-authentication-provider.html">DaoAuthenticationProvider</a>
</li>
<li class="nav-item" data-depth="5">
<a class="nav-link" href="../../../servlet/authentication/passwords/ldap.html">LDAP</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authentication/session-management.html">Session Management</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authentication/rememberme.html">Remember Me</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authentication/openid.html">OpenID</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authentication/anonymous.html">Anonymous</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authentication/preauth.html">Pre-Authentication</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authentication/jaas.html">JAAS</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authentication/cas.html">CAS</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authentication/x509.html">X509</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authentication/runas.html">Run-As</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authentication/logout.html">Logout</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authentication/events.html">Authentication Events</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/authorization/index.html">Authorization</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authorization/architecture.html">Authorization Architecture</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authorization/authorize-requests.html">Authorize HTTP Requests</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authorization/expression-based.html">Expression-Based Access Control</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authorization/secure-objects.html">Secure Object Implementations</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authorization/method-security.html">Method Security</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/authorization/acls.html">Domain Object Security ACLs</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/oauth2/index.html">OAuth2</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/oauth2/login/index.html">OAuth2 Log In</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/oauth2/login/core.html">Core Configuration</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/oauth2/login/advanced.html">Advanced Configuration</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/oauth2/client/index.html">OAuth2 Client</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/oauth2/client/core.html">Core Interfaces and Classes</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/oauth2/client/authorization-grants.html">OAuth2 Authorization Grants</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/oauth2/client/client-authentication.html">OAuth2 Client Authentication</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/oauth2/client/authorized-clients.html">OAuth2 Authorized Clients</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/oauth2/resource-server/index.html">OAuth2 Resource Server</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/oauth2/resource-server/jwt.html">JWT</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/oauth2/resource-server/opaque-token.html">Opaque Token</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/oauth2/resource-server/multitenancy.html">Multitenancy</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/oauth2/resource-server/bearer-tokens.html">Bearer Tokens</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/saml2/index.html">SAML2</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/saml2/login/index.html">SAML2 Log In</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/saml2/login/overview.html">SAML2 Log In Overview</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/saml2/login/authentication-requests.html">SAML2 Authentication Requests</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/saml2/login/authentication.html">SAML2 Authentication Responses</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/saml2/logout.html">SAML2 Logout</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/saml2/metadata.html">SAML2 Metadata</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/exploits/index.html">Protection Against Exploits</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/exploits/csrf.html">Cross Site Request Forgery (CSRF) for Servlet Environments</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/exploits/headers.html">Security HTTP Response Headers</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/exploits/http.html">HTTP</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/exploits/firewall.html">HttpFirewall</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/integrations/index.html">Integrations</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/integrations/concurrency.html">Concurrency</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/integrations/jackson.html">Jackson</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/integrations/localization.html">Localization</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/integrations/servlet-api.html">Servlet APIs</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/integrations/data.html">Spring Data</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/integrations/mvc.html">Spring MVC</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/integrations/websocket.html">WebSocket</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/integrations/cors.html">Spring&#8217;s CORS Support</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/integrations/jsp-taglibs.html">JSP Taglib</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">Configuration</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/configuration/java.html">Java Configuration</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/configuration/kotlin.html">Kotlin Configuration</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/configuration/xml-namespace.html">Namespace Configuration</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/test/index.html">Testing</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/test/method.html">Method Security</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/test/mockmvc/index.html">MockMvc Support</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/test/mockmvc/setup.html">MockMvc Setup</a>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/test/mockmvc/request-post-processors.html">Security RequestPostProcessors</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/test/mockmvc/authentication.html">Mocking Users</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/test/mockmvc/csrf.html">Mocking CSRF</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/test/mockmvc/form-login.html">Mocking Form Login</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/test/mockmvc/http-basic.html">Mocking HTTP Basic</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/test/mockmvc/oauth2.html">Mocking OAuth2</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/test/mockmvc/logout.html">Mocking Logout</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/test/mockmvc/request-builders.html">Security RequestBuilders</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/test/mockmvc/result-matchers.html">Security ResultMatchers</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/test/mockmvc/result-handlers.html">Security ResultHandlers</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/appendix/index.html">Appendix</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/appendix/database-schema.html">Database Schemas</a>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../../servlet/appendix/namespace/index.html">XML Namespace</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/appendix/namespace/authentication-manager.html">Authentication Services</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/appendix/namespace/http.html">Web Security</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/appendix/namespace/method-security.html">Method Security</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/appendix/namespace/ldap.html">LDAP Security</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../../servlet/appendix/namespace/websocket.html">WebSocket Security</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../../servlet/appendix/faq.html">FAQ</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item" data-depth="1">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../index.html">Reactive Applications</a>
<ul class="nav-list">
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../../getting-started.html">Getting Started</a>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">Authentication</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../authentication/x509.html">X.509 Authentication</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../authentication/logout.html">Logout</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">Authorization</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../authorization/method.html">EnableReactiveMethodSecurity</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../oauth2/index.html">OAuth2</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../oauth2/login/index.html">OAuth2 Log In</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../oauth2/login/core.html">Core Configuration</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../oauth2/login/advanced.html">Advanced Configuration</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../oauth2/client/index.html">OAuth2 Client</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../oauth2/client/core.html">Core Interfaces and Classes</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../oauth2/client/authorization-grants.html">OAuth2 Authorization Grants</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../oauth2/client/client-authentication.html">OAuth2 Client Authentication</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../oauth2/client/authorized-clients.html">OAuth2 Authorized Clients</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../oauth2/resource-server/index.html">OAuth2 Resource Server</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../oauth2/resource-server/jwt.html">JWT</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../oauth2/resource-server/opaque-token.html">Opaque Token</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../oauth2/resource-server/multitenancy.html">Multitenancy</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="../../oauth2/resource-server/bearer-tokens.html">Bearer Tokens</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../../exploits/index.html">Protection Against Exploits</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../exploits/csrf.html">CSRF</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../exploits/headers.html">Headers</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../exploits/http.html">HTTP Requests</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<span class="nav-text">Integrations</span>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../integrations/cors.html">CORS</a>
</li>
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../../integrations/rsocket.html">RSocket</a>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="../index.html">Testing</a>
<ul class="nav-list">
<li class="nav-item" data-depth="3">
<a class="nav-link" href="../method.html">Testing Method Security</a>
</li>
<li class="nav-item" data-depth="3">
<button class="nav-item-toggle"></button>
<a class="nav-link" href="index.html">Testing Web Security</a>
<ul class="nav-list">
<li class="nav-item" data-depth="4">
<a class="nav-link" href="setup.html">WebTestClient Setup</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="authentication.html">Testing Authentication</a>
</li>
<li class="nav-item" data-depth="4">
<a class="nav-link" href="csrf.html">Testing CSRF</a>
</li>
<li class="nav-item is-current-page" data-depth="4">
<a class="nav-link" href="oauth2.html">Testing OAuth 2.0</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="nav-item" data-depth="2">
<a class="nav-link" href="../../configuration/webflux.html">WebFlux Security</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</div>
<div class="nav-panel-explore" data-panel="explore">
<div class="context">
<span class="title">Spring Security</span>
<span class="version">5.6.0</span>
</div>
<ul class="components">
<li class="component is-current">
<a class="title" href="../../../../index.html">Spring Security</a>
<ul class="versions">
<li class="version">
<a href="../../../../6.0/index.html">6.0.0-SNAPSHOT</a>
</li>
<li class="version">
<a href="../../../../6.0.0-M3/index.html">6.0.0-M3</a>
</li>
<li class="version">
<a href="../../../../6.0.0-M2/index.html">6.0.0-M2</a>
</li>
<li class="version">
<a href="../../../../6.0.0-M1/index.html">6.0.0-M1</a>
</li>
<li class="version">
<a href="../../../../5.7/index.html">5.7.0-SNAPSHOT</a>
</li>
<li class="version">
<a href="../../../../5.7.0-RC1/index.html">5.7.0-RC1</a>
</li>
<li class="version">
<a href="../../../../5.7.0-M3/index.html">5.7.0-M3</a>
</li>
<li class="version">
<a href="../../../../5.7.0-M2/index.html">5.7.0-M2</a>
</li>
<li class="version">
<a href="../../../../5.7.0-M1/index.html">5.7.0-M1</a>
</li>
<li class="version">
<a href="../../../../5.6.4/index.html">5.6.4-SNAPSHOT</a>
</li>
<li class="version is-latest">
<a href="../../../../index.html">5.6.3</a>
</li>
<li class="version">
<a href="../../../../5.6.2/index.html">5.6.2</a>
</li>
<li class="version">
<a href="../../../../5.6.1/index.html">5.6.1</a>
</li>
<li class="version is-current">
<a href="../../../index.html">5.6.0</a>
</li>
<li class="version">
<a href="../../../../5.6.0-RC1/index.html">5.6.0-RC1</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</aside>
</div>
<main class="article">
<div class="toolbar" role="navigation">
<button class="nav-toggle"></button>
<nav class="breadcrumbs" aria-label="breadcrumbs">
<ul>
<li><a href="../../../index.html">Spring Security</a></li>
<li><a href="../../index.html">Reactive Applications</a></li>
<li><a href="../index.html">Testing</a></li>
<li><a href="index.html">Testing Web Security</a></li>
<li><a href="oauth2.html">Testing OAuth 2.0</a></li>
</ul>
</nav>
<div class="search">
<input id="search-input" type="text" placeholder="Search docs">
</div>
<div class="page-versions">
<button class="version-menu-toggle" title="Show other versions of page">5.6.0</button>
<div class="version-menu">
<a class="version" href="../../../../6.0/reactive/test/web/oauth2.html">6.0.0-SNAPSHOT</a>
<a class="version" href="../../../../6.0.0-M3/reactive/test/web/oauth2.html">6.0.0-M3</a>
<a class="version" href="../../../../6.0.0-M2/reactive/test/web/oauth2.html">6.0.0-M2</a>
<a class="version" href="../../../../6.0.0-M1/reactive/test/web/oauth2.html">6.0.0-M1</a>
<a class="version" href="../../../../5.7/reactive/test/web/oauth2.html">5.7.0-SNAPSHOT</a>
<a class="version" href="../../../../5.7.0-RC1/reactive/test/web/oauth2.html">5.7.0-RC1</a>
<a class="version" href="../../../../5.7.0-M3/reactive/test/web/oauth2.html">5.7.0-M3</a>
<a class="version" href="../../../../5.7.0-M2/reactive/test/web/oauth2.html">5.7.0-M2</a>
<a class="version" href="../../../../5.7.0-M1/reactive/test/web/oauth2.html">5.7.0-M1</a>
<a class="version" href="../../../../5.6.4/reactive/test/web/oauth2.html">5.6.4-SNAPSHOT</a>
<a class="version" href="../../../../reactive/test/web/oauth2.html">5.6.3</a>
<a class="version" href="../../../../5.6.2/reactive/test/web/oauth2.html">5.6.2</a>
<a class="version" href="../../../../5.6.1/reactive/test/web/oauth2.html">5.6.1</a>
<a class="version is-current" href="oauth2.html">5.6.0</a>
<a class="version is-missing" href="../../../../5.6.0-RC1/index.html">5.6.0-RC1</a>
</div>
</div>
<div class="edit-this-page"><a href="https://github.com/spring-projects/spring-security/blob/5.6.0/docs/modules/ROOT/pages/reactive/test/web/oauth2.adoc">Edit this Page</a></div>
</div>
<div class="content">
<aside class="toc sidebar" data-title="Contents" data-levels="2">
<div class="toc-menu"></div>
</aside>
<article class="doc">
<div class="admonitionblock important">
<table>
<tbody><tr>
<td class="icon">
<i class="fa icon-important" title="Important"></i>
</td>
<td class="content">
<div class="paragraph">
<p> For the latest stable version, please use <a href="../../../../reactive/test/web/oauth2.html">Spring Security 5.6.3</a>!</p>
</div>
</td>
</tr></tbody>
</table>
</div>
<h1 id="page-title" class="page">Testing OAuth 2.0</h1>
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>When it comes to OAuth 2.0, <a href="../method.html#test-erms" class="xref page">the same principles covered earlier still apply</a>: Ultimately, it depends on what your method under test is expecting to be in the <code>SecurityContextHolder</code>.</p>
</div>
<div class="paragraph">
<p>For example, for a controller that looks like this:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@GetMapping("/endpoint")
public Mono&lt;String&gt; foo(Principal user) {
    return Mono.just(user.getName());
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">@GetMapping("/endpoint")
fun foo(user: Principal): Mono&lt;String&gt; {
    return Mono.just(user.name)
}</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>There&#8217;s nothing OAuth2-specific about it, so you will likely be able to simply <a href="../method.html#test-erms" class="xref page">use <code>@WithMockUser</code></a> and be fine.</p>
</div>
<div class="paragraph">
<p>But, in cases where your controllers are bound to some aspect of Spring Security&#8217;s OAuth 2.0 support, like the following:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@GetMapping("/endpoint")
public Mono&lt;String&gt; foo(@AuthenticationPrincipal OidcUser user) {
    return Mono.just(user.getIdToken().getSubject());
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">@GetMapping("/endpoint")
fun foo(@AuthenticationPrincipal user: OidcUser): Mono&lt;String&gt; {
    return Mono.just(user.idToken.subject)
}</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>then Spring Security&#8217;s test support can come in handy.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="webflux-testing-oidc-login"><a class="anchor" href="oauth2.html#webflux-testing-oidc-login"></a>Testing OIDC Login</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Testing the method above with <code>WebTestClient</code> would require simulating some kind of grant flow with an authorization server.
Certainly this would be a daunting task, which is why Spring Security ships with support for removing this boilerplate.</p>
</div>
<div class="paragraph">
<p>For example, we can tell Spring Security to include a default <code>OidcUser</code> using the <code>SecurityMockServerConfigurers#mockOidcLogin</code> method, like so:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">client
    .mutateWith(mockOidcLogin()).get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">client
    .mutateWith(mockOidcLogin())
    .get().uri("/endpoint")
    .exchange()</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>What this will do is configure the associated <code>MockServerRequest</code> with an <code>OidcUser</code> that includes a simple <code>OidcIdToken</code>, <code>OidcUserInfo</code>, and <code>Collection</code> of granted authorities.</p>
</div>
<div class="paragraph">
<p>Specifically, it will include an <code>OidcIdToken</code> with a <code>sub</code> claim set to <code>user</code>:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">assertThat(user.getIdToken().getClaim("sub")).isEqualTo("user");</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">assertThat(user.idToken.getClaim&lt;String&gt;("sub")).isEqualTo("user")</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>an <code>OidcUserInfo</code> with no claims set:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">assertThat(user.getUserInfo().getClaims()).isEmpty();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">assertThat(user.userInfo.claims).isEmpty()</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>and a <code>Collection</code> of authorities with just one authority, <code>SCOPE_read</code>:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">assertThat(user.getAuthorities()).hasSize(1);
assertThat(user.getAuthorities()).containsExactly(new SimpleGrantedAuthority("SCOPE_read"));</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">assertThat(user.authorities).hasSize(1)
assertThat(user.authorities).containsExactly(SimpleGrantedAuthority("SCOPE_read"))</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Spring Security does the necessary work to make sure that the <code>OidcUser</code> instance is available for <a href="../../../servlet/integrations/mvc.html#mvc-authentication-principal" class="xref page">the <code>@AuthenticationPrincipal</code> annotation</a>.</p>
</div>
<div class="paragraph">
<p>Further, it also links that <code>OidcUser</code> to a simple instance of <code>OAuth2AuthorizedClient</code> that it deposits into a mock <code>ServerOAuth2AuthorizedClientRepository</code>.
This can be handy if your tests <a href="oauth2.html#webflux-testing-oauth2-client">use the <code>@RegisteredOAuth2AuthorizedClient</code> annotation</a>..</p>
</div>
<div class="sect2">
<h3 id="webflux-testing-oidc-login-authorities"><a class="anchor" href="oauth2.html#webflux-testing-oidc-login-authorities"></a>Configuring Authorities</h3>
<div class="paragraph">
<p>In many circumstances, your method is protected by filter or method security and needs your <code>Authentication</code> to have certain granted authorities to allow the request.</p>
</div>
<div class="paragraph">
<p>In this case, you can supply what granted authorities you need using the <code>authorities()</code> method:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">client
    .mutateWith(mockOidcLogin()
        .authorities(new SimpleGrantedAuthority("SCOPE_message:read"))
    )
    .get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">client
    .mutateWith(mockOidcLogin()
        .authorities(SimpleGrantedAuthority("SCOPE_message:read"))
    )
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="webflux-testing-oidc-login-claims"><a class="anchor" href="oauth2.html#webflux-testing-oidc-login-claims"></a>Configuring Claims</h3>
<div class="paragraph">
<p>And while granted authorities are quite common across all of Spring Security, we also have claims in the case of OAuth 2.0.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s say, for example, that you&#8217;ve got a <code>user_id</code> claim that indicates the user&#8217;s id in your system.
You might access it like so in a controller:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@GetMapping("/endpoint")
public Mono&lt;String&gt; foo(@AuthenticationPrincipal OidcUser oidcUser) {
    String userId = oidcUser.getIdToken().getClaim("user_id");
    // ...
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">@GetMapping("/endpoint")
fun foo(@AuthenticationPrincipal oidcUser: OidcUser): Mono&lt;String&gt; {
    val userId = oidcUser.idToken.getClaim&lt;String&gt;("user_id")
    // ...
}</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>In that case, you&#8217;d want to specify that claim with the <code>idToken()</code> method:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">client
    .mutateWith(mockOidcLogin()
        .idToken(token -&gt; token.claim("user_id", "1234"))
    )
    .get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">client
    .mutateWith(mockOidcLogin()
        .idToken { token -&gt; token.claim("user_id", "1234") }
    )
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>since <code>OidcUser</code> collects its claims from <code>OidcIdToken</code>.</p>
</div>
</div>
<div class="sect2">
<h3 id="webflux-testing-oidc-login-user"><a class="anchor" href="oauth2.html#webflux-testing-oidc-login-user"></a>Additional Configurations</h3>
<div class="paragraph">
<p>There are additional methods, too, for further configuring the authentication; it simply depends on what data your controller expects:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>userInfo(OidcUserInfo.Builder)</code> - For configuring the <code>OidcUserInfo</code> instance</p>
</li>
<li>
<p><code>clientRegistration(ClientRegistration)</code> - For configuring the associated <code>OAuth2AuthorizedClient</code> with a given <code>ClientRegistration</code></p>
</li>
<li>
<p><code>oidcUser(OidcUser)</code> - For configuring the complete <code>OidcUser</code> instance</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>That last one is handy if you:
1. Have your own implementation of <code>OidcUser</code>, or
2. Need to change the name attribute</p>
</div>
<div class="paragraph">
<p>For example, let&#8217;s say that your authorization server sends the principal name in the <code>user_name</code> claim instead of the <code>sub</code> claim.
In that case, you can configure an <code>OidcUser</code> by hand:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">OidcUser oidcUser = new DefaultOidcUser(
        AuthorityUtils.createAuthorityList("SCOPE_message:read"),
        OidcIdToken.withTokenValue("id-token").claim("user_name", "foo_user").build(),
        "user_name");

client
    .mutateWith(mockOidcLogin().oidcUser(oidcUser))
    .get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">val oidcUser: OidcUser = DefaultOidcUser(
    AuthorityUtils.createAuthorityList("SCOPE_message:read"),
    OidcIdToken.withTokenValue("id-token").claim("user_name", "foo_user").build(),
    "user_name"
)

client
    .mutateWith(mockOidcLogin().oidcUser(oidcUser))
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="webflux-testing-oauth2-login"><a class="anchor" href="oauth2.html#webflux-testing-oauth2-login"></a>Testing OAuth 2.0 Login</h2>
<div class="sectionbody">
<div class="paragraph">
<p>As with <a href="oauth2.html#webflux-testing-oidc-login">testing OIDC login</a>, testing OAuth 2.0 Login presents a similar challenge of mocking a grant flow.
And because of that, Spring Security also has test support for non-OIDC use cases.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s say that we&#8217;ve got a controller that gets the logged-in user as an <code>OAuth2User</code>:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@GetMapping("/endpoint")
public Mono&lt;String&gt; foo(@AuthenticationPrincipal OAuth2User oauth2User) {
    return Mono.just(oauth2User.getAttribute("sub"));
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">@GetMapping("/endpoint")
fun foo(@AuthenticationPrincipal oauth2User: OAuth2User): Mono&lt;String&gt; {
    return Mono.just(oauth2User.getAttribute("sub"))
}</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>In that case, we can tell Spring Security to include a default <code>OAuth2User</code> using the <code>SecurityMockServerConfigurers#mockOAuth2Login</code> method, like so:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">client
    .mutateWith(mockOAuth2Login())
    .get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">client
    .mutateWith(mockOAuth2Login())
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>What this will do is configure the associated <code>MockServerRequest</code> with an <code>OAuth2User</code> that includes a simple <code>Map</code> of attributes and <code>Collection</code> of granted authorities.</p>
</div>
<div class="paragraph">
<p>Specifically, it will include a <code>Map</code> with a key/value pair of <code>sub</code>/<code>user</code>:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">assertThat((String) user.getAttribute("sub")).isEqualTo("user");</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">assertThat(user.getAttribute&lt;String&gt;("sub")).isEqualTo("user")</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>and a <code>Collection</code> of authorities with just one authority, <code>SCOPE_read</code>:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">assertThat(user.getAuthorities()).hasSize(1);
assertThat(user.getAuthorities()).containsExactly(new SimpleGrantedAuthority("SCOPE_read"));</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">assertThat(user.authorities).hasSize(1)
assertThat(user.authorities).containsExactly(SimpleGrantedAuthority("SCOPE_read"))</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Spring Security does the necessary work to make sure that the <code>OAuth2User</code> instance is available for <a href="../../../servlet/integrations/mvc.html#mvc-authentication-principal" class="xref page">the <code>@AuthenticationPrincipal</code> annotation</a>.</p>
</div>
<div class="paragraph">
<p>Further, it also links that <code>OAuth2User</code> to a simple instance of <code>OAuth2AuthorizedClient</code> that it deposits in a mock <code>ServerOAuth2AuthorizedClientRepository</code>.
This can be handy if your tests <a href="oauth2.html#webflux-testing-oauth2-client">use the <code>@RegisteredOAuth2AuthorizedClient</code> annotation</a>.</p>
</div>
<div class="sect2">
<h3 id="webflux-testing-oauth2-login-authorities"><a class="anchor" href="oauth2.html#webflux-testing-oauth2-login-authorities"></a>Configuring Authorities</h3>
<div class="paragraph">
<p>In many circumstances, your method is protected by filter or method security and needs your <code>Authentication</code> to have certain granted authorities to allow the request.</p>
</div>
<div class="paragraph">
<p>In this case, you can supply what granted authorities you need using the <code>authorities()</code> method:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">client
    .mutateWith(mockOAuth2Login()
        .authorities(new SimpleGrantedAuthority("SCOPE_message:read"))
    )
    .get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">client
    .mutateWith(mockOAuth2Login()
        .authorities(SimpleGrantedAuthority("SCOPE_message:read"))
    )
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="webflux-testing-oauth2-login-claims"><a class="anchor" href="oauth2.html#webflux-testing-oauth2-login-claims"></a>Configuring Claims</h3>
<div class="paragraph">
<p>And while granted authorities are quite common across all of Spring Security, we also have claims in the case of OAuth 2.0.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s say, for example, that you&#8217;ve got a <code>user_id</code> attribute that indicates the user&#8217;s id in your system.
You might access it like so in a controller:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@GetMapping("/endpoint")
public Mono&lt;String&gt; foo(@AuthenticationPrincipal OAuth2User oauth2User) {
    String userId = oauth2User.getAttribute("user_id");
    // ...
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">@GetMapping("/endpoint")
fun foo(@AuthenticationPrincipal oauth2User: OAuth2User): Mono&lt;String&gt; {
    val userId = oauth2User.getAttribute&lt;String&gt;("user_id")
    // ...
}</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>In that case, you&#8217;d want to specify that attribute with the <code>attributes()</code> method:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">client
    .mutateWith(mockOAuth2Login()
        .attributes(attrs -&gt; attrs.put("user_id", "1234"))
    )
    .get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">client
    .mutateWith(mockOAuth2Login()
        .attributes { attrs -&gt; attrs["user_id"] = "1234" }
    )
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="webflux-testing-oauth2-login-user"><a class="anchor" href="oauth2.html#webflux-testing-oauth2-login-user"></a>Additional Configurations</h3>
<div class="paragraph">
<p>There are additional methods, too, for further configuring the authentication; it simply depends on what data your controller expects:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>clientRegistration(ClientRegistration)</code> - For configuring the associated <code>OAuth2AuthorizedClient</code> with a given <code>ClientRegistration</code></p>
</li>
<li>
<p><code>oauth2User(OAuth2User)</code> - For configuring the complete <code>OAuth2User</code> instance</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>That last one is handy if you:
1. Have your own implementation of <code>OAuth2User</code>, or
2. Need to change the name attribute</p>
</div>
<div class="paragraph">
<p>For example, let&#8217;s say that your authorization server sends the principal name in the <code>user_name</code> claim instead of the <code>sub</code> claim.
In that case, you can configure an <code>OAuth2User</code> by hand:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">OAuth2User oauth2User = new DefaultOAuth2User(
        AuthorityUtils.createAuthorityList("SCOPE_message:read"),
        Collections.singletonMap("user_name", "foo_user"),
        "user_name");

client
    .mutateWith(mockOAuth2Login().oauth2User(oauth2User))
    .get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">val oauth2User: OAuth2User = DefaultOAuth2User(
    AuthorityUtils.createAuthorityList("SCOPE_message:read"),
    mapOf(Pair("user_name", "foo_user")),
    "user_name"
)

client
    .mutateWith(mockOAuth2Login().oauth2User(oauth2User))
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="webflux-testing-oauth2-client"><a class="anchor" href="oauth2.html#webflux-testing-oauth2-client"></a>Testing OAuth 2.0 Clients</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Independent of how your user authenticates, you may have other tokens and client registrations that are in play for the request you are testing.
For example, your controller may be relying on the client credentials grant to get a token that isn&#8217;t associated with the user at all:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@GetMapping("/endpoint")
public Mono&lt;String&gt; foo(@RegisteredOAuth2AuthorizedClient("my-app") OAuth2AuthorizedClient authorizedClient) {
    return this.webClient.get()
        .attributes(oauth2AuthorizedClient(authorizedClient))
        .retrieve()
        .bodyToMono(String.class);
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">import org.springframework.web.reactive.function.client.bodyToMono

// ...

@GetMapping("/endpoint")
fun foo(@RegisteredOAuth2AuthorizedClient("my-app") authorizedClient: OAuth2AuthorizedClient?): Mono&lt;String&gt; {
    return this.webClient.get()
        .attributes(oauth2AuthorizedClient(authorizedClient))
        .retrieve()
        .bodyToMono()
}</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Simulating this handshake with the authorization server could be cumbersome.
Instead, you can use <code>SecurityMockServerConfigurers#mockOAuth2Client</code> to add a <code>OAuth2AuthorizedClient</code> into a mock <code>ServerOAuth2AuthorizedClientRepository</code>:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">client
    .mutateWith(mockOAuth2Client("my-app"))
    .get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">client
    .mutateWith(mockOAuth2Client("my-app"))
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>What this will do is create an <code>OAuth2AuthorizedClient</code> that has a simple <code>ClientRegistration</code>, <code>OAuth2AccessToken</code>, and resource owner name.</p>
</div>
<div class="paragraph">
<p>Specifically, it will include a <code>ClientRegistration</code> with a client id of "test-client" and client secret of "test-secret":</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">assertThat(authorizedClient.getClientRegistration().getClientId()).isEqualTo("test-client");
assertThat(authorizedClient.getClientRegistration().getClientSecret()).isEqualTo("test-secret");</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">assertThat(authorizedClient.clientRegistration.clientId).isEqualTo("test-client")
assertThat(authorizedClient.clientRegistration.clientSecret).isEqualTo("test-secret")</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>a resource owner name of "user":</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">assertThat(authorizedClient.getPrincipalName()).isEqualTo("user");</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">assertThat(authorizedClient.principalName).isEqualTo("user")</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>and an <code>OAuth2AccessToken</code> with just one scope, <code>read</code>:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">assertThat(authorizedClient.getAccessToken().getScopes()).hasSize(1);
assertThat(authorizedClient.getAccessToken().getScopes()).containsExactly("read");</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">assertThat(authorizedClient.accessToken.scopes).hasSize(1)
assertThat(authorizedClient.accessToken.scopes).containsExactly("read")</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>The client can then be retrieved as normal using <code>@RegisteredOAuth2AuthorizedClient</code> in a controller method.</p>
</div>
<div class="sect2">
<h3 id="webflux-testing-oauth2-client-scopes"><a class="anchor" href="oauth2.html#webflux-testing-oauth2-client-scopes"></a>Configuring Scopes</h3>
<div class="paragraph">
<p>In many circumstances, the OAuth 2.0 access token comes with a set of scopes.
If your controller inspects these, say like so:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@GetMapping("/endpoint")
public Mono&lt;String&gt; foo(@RegisteredOAuth2AuthorizedClient("my-app") OAuth2AuthorizedClient authorizedClient) {
    Set&lt;String&gt; scopes = authorizedClient.getAccessToken().getScopes();
    if (scopes.contains("message:read")) {
        return this.webClient.get()
            .attributes(oauth2AuthorizedClient(authorizedClient))
            .retrieve()
            .bodyToMono(String.class);
    }
    // ...
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">import org.springframework.web.reactive.function.client.bodyToMono

// ...

@GetMapping("/endpoint")
fun foo(@RegisteredOAuth2AuthorizedClient("my-app") authorizedClient: OAuth2AuthorizedClient): Mono&lt;String&gt; {
    val scopes = authorizedClient.accessToken.scopes
    if (scopes.contains("message:read")) {
        return webClient.get()
            .attributes(oauth2AuthorizedClient(authorizedClient))
            .retrieve()
            .bodyToMono()
    }
    // ...
}</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>then you can configure the scope using the <code>accessToken()</code> method:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">client
    .mutateWith(mockOAuth2Client("my-app")
        .accessToken(new OAuth2AccessToken(BEARER, "token", null, null, Collections.singleton("message:read")))
    )
    .get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">client
    .mutateWith(mockOAuth2Client("my-app")
        .accessToken(OAuth2AccessToken(BEARER, "token", null, null, setOf("message:read")))
)
.get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="webflux-testing-oauth2-client-registration"><a class="anchor" href="oauth2.html#webflux-testing-oauth2-client-registration"></a>Additional Configurations</h3>
<div class="paragraph">
<p>There are additional methods, too, for further configuring the authentication; it simply depends on what data your controller expects:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>principalName(String)</code> - For configuring the resource owner name</p>
</li>
<li>
<p><code>clientRegistration(Consumer&lt;ClientRegistration.Builder&gt;)</code> - For configuring the associated <code>ClientRegistration</code></p>
</li>
<li>
<p><code>clientRegistration(ClientRegistration)</code> - For configuring the complete <code>ClientRegistration</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>That last one is handy if you want to use a real <code>ClientRegistration</code></p>
</div>
<div class="paragraph">
<p>For example, let&#8217;s say that you are wanting to use one of your app&#8217;s <code>ClientRegistration</code> definitions, as specified in your <code>application.yml</code>.</p>
</div>
<div class="paragraph">
<p>In that case, your test can autowire the <code>ReactiveClientRegistrationRepository</code> and look up the one your test needs:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@Autowired
ReactiveClientRegistrationRepository clientRegistrationRepository;

// ...

client
    .mutateWith(mockOAuth2Client()
        .clientRegistration(this.clientRegistrationRepository.findByRegistrationId("facebook").block())
    )
    .get().uri("/exchange").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">@Autowired
lateinit var clientRegistrationRepository: ReactiveClientRegistrationRepository

// ...

client
    .mutateWith(mockOAuth2Client()
        .clientRegistration(this.clientRegistrationRepository.findByRegistrationId("facebook").block())
    )
    .get().uri("/exchange").exchange()</code></pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="webflux-testing-jwt"><a class="anchor" href="oauth2.html#webflux-testing-jwt"></a>Testing JWT Authentication</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In order to make an authorized request on a resource server, you need a bearer token.
If your resource server is configured for JWTs, then this would mean that the bearer token needs to be signed and then encoded according to the JWT specification.
All of this can be quite daunting, especially when this isn&#8217;t the focus of your test.</p>
</div>
<div class="paragraph">
<p>Fortunately, there are a number of simple ways that you can overcome this difficulty and allow your tests to focus on authorization and not on representing bearer tokens.
We&#8217;ll look at two of them now:</p>
</div>
<div class="sect2">
<h3 id="_mockjwt_webtestclientconfigurer"><a class="anchor" href="oauth2.html#_mockjwt_webtestclientconfigurer"></a><code>mockJwt() WebTestClientConfigurer</code></h3>
<div class="paragraph">
<p>The first way is via a <code>WebTestClientConfigurer</code>.
The simplest of these would be to use the <code>SecurityMockServerConfigurers#mockJwt</code> method like the following:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">client
    .mutateWith(mockJwt()).get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">client
    .mutateWith(mockJwt()).get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>What this will do is create a mock <code>Jwt</code>, passing it correctly through any authentication APIs so that it&#8217;s available for your authorization mechanisms to verify.</p>
</div>
<div class="paragraph">
<p>By default, the <code>JWT</code> that it creates has the following characteristics:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-json hljs" data-lang="json">{
  "headers" : { "alg" : "none" },
  "claims" : {
    "sub" : "user",
    "scope" : "read"
  }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>And the resulting <code>Jwt</code>, were it tested, would pass in the following way:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">assertThat(jwt.getTokenValue()).isEqualTo("token");
assertThat(jwt.getHeaders().get("alg")).isEqualTo("none");
assertThat(jwt.getSubject()).isEqualTo("sub");</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">assertThat(jwt.tokenValue).isEqualTo("token")
assertThat(jwt.headers["alg"]).isEqualTo("none")
assertThat(jwt.subject).isEqualTo("sub")</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>These values can, of course be configured.</p>
</div>
<div class="paragraph">
<p>Any headers or claims can be configured with their corresponding methods:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">client
	.mutateWith(mockJwt().jwt(jwt -&gt; jwt.header("kid", "one")
		.claim("iss", "https://idp.example.org")))
	.get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">client
    .mutateWith(mockJwt().jwt { jwt -&gt; jwt.header("kid", "one")
        .claim("iss", "https://idp.example.org")
    })
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">client
	.mutateWith(mockJwt().jwt(jwt -&gt; jwt.claims(claims -&gt; claims.remove("scope"))))
	.get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">client
    .mutateWith(mockJwt().jwt { jwt -&gt;
        jwt.claims { claims -&gt; claims.remove("scope") }
    })
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>The <code>scope</code> and <code>scp</code> claims are processed the same way here as they are in a normal bearer token request.
However, this can be overridden simply by providing the list of <code>GrantedAuthority</code> instances that you need for your test:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">client
	.mutateWith(mockJwt().authorities(new SimpleGrantedAuthority("SCOPE_messages")))
	.get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">client
    .mutateWith(mockJwt().authorities(SimpleGrantedAuthority("SCOPE_messages")))
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Or, if you have a custom <code>Jwt</code> to <code>Collection&lt;GrantedAuthority&gt;</code> converter, you can also use that to derive the authorities:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">client
	.mutateWith(mockJwt().authorities(new MyConverter()))
	.get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">client
    .mutateWith(mockJwt().authorities(MyConverter()))
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>You can also specify a complete <code>Jwt</code>, for which <code><a href="https://docs.spring.io/spring-security/site/docs/5.6.0/api/org/springframework/security/oauth2/jwt/Jwt.Builder.html">Jwt.Builder</a></code> comes quite handy:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">Jwt jwt = Jwt.withTokenValue("token")
    .header("alg", "none")
    .claim("sub", "user")
    .claim("scope", "read")
    .build();

client
	.mutateWith(mockJwt().jwt(jwt))
	.get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">val jwt: Jwt = Jwt.withTokenValue("token")
    .header("alg", "none")
    .claim("sub", "user")
    .claim("scope", "read")
    .build()

client
    .mutateWith(mockJwt().jwt(jwt))
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_authentication_webtestclientconfigurer"><a class="anchor" href="oauth2.html#_authentication_webtestclientconfigurer"></a><code>authentication()</code> <code>WebTestClientConfigurer</code></h3>
<div class="paragraph">
<p>The second way is by using the <code>authentication()</code> <code>Mutator</code>.
Essentially, you can instantiate your own <code>JwtAuthenticationToken</code> and provide it in your test, like so:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">Jwt jwt = Jwt.withTokenValue("token")
    .header("alg", "none")
    .claim("sub", "user")
    .build();
Collection&lt;GrantedAuthority&gt; authorities = AuthorityUtils.createAuthorityList("SCOPE_read");
JwtAuthenticationToken token = new JwtAuthenticationToken(jwt, authorities);

client
	.mutateWith(mockAuthentication(token))
	.get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">val jwt = Jwt.withTokenValue("token")
    .header("alg", "none")
    .claim("sub", "user")
    .build()
val authorities: Collection&lt;GrantedAuthority&gt; = AuthorityUtils.createAuthorityList("SCOPE_read")
val token = JwtAuthenticationToken(jwt, authorities)

client
    .mutateWith(mockAuthentication&lt;JwtMutator&gt;(token))
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Note that as an alternative to these, you can also mock the <code>ReactiveJwtDecoder</code> bean itself with a <code>@MockBean</code> annotation.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="webflux-testing-opaque-token"><a class="anchor" href="oauth2.html#webflux-testing-opaque-token"></a>Testing Opaque Token Authentication</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Similar to <a href="oauth2.html#webflux-testing-jwt">JWTs</a>, opaque tokens require an authorization server in order to verify their validity, which can make testing more difficult.
To help with that, Spring Security has test support for opaque tokens.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s say that we&#8217;ve got a controller that retrieves the authentication as a <code>BearerTokenAuthentication</code>:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@GetMapping("/endpoint")
public Mono&lt;String&gt; foo(BearerTokenAuthentication authentication) {
    return Mono.just((String) authentication.getTokenAttributes().get("sub"));
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">@GetMapping("/endpoint")
fun foo(authentication: BearerTokenAuthentication): Mono&lt;String?&gt; {
    return Mono.just(authentication.tokenAttributes["sub"] as String?)
}</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>In that case, we can tell Spring Security to include a default <code>BearerTokenAuthentication</code> using the <code>SecurityMockServerConfigurers#mockOpaqueToken</code> method, like so:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">client
    .mutateWith(mockOpaqueToken())
    .get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">client
    .mutateWith(mockOpaqueToken())
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>What this will do is configure the associated <code>MockHttpServletRequest</code> with a <code>BearerTokenAuthentication</code> that includes a simple <code>OAuth2AuthenticatedPrincipal</code>, <code>Map</code> of attributes, and <code>Collection</code> of granted authorities.</p>
</div>
<div class="paragraph">
<p>Specifically, it will include a <code>Map</code> with a key/value pair of <code>sub</code>/<code>user</code>:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">assertThat((String) token.getTokenAttributes().get("sub")).isEqualTo("user");</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">assertThat(token.tokenAttributes["sub"] as String?).isEqualTo("user")</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>and a <code>Collection</code> of authorities with just one authority, <code>SCOPE_read</code>:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">assertThat(token.getAuthorities()).hasSize(1);
assertThat(token.getAuthorities()).containsExactly(new SimpleGrantedAuthority("SCOPE_read"));</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">assertThat(token.authorities).hasSize(1)
assertThat(token.authorities).containsExactly(SimpleGrantedAuthority("SCOPE_read"))</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Spring Security does the necessary work to make sure that the <code>BearerTokenAuthentication</code> instance is available for your controller methods.</p>
</div>
<div class="sect2">
<h3 id="webflux-testing-opaque-token-authorities"><a class="anchor" href="oauth2.html#webflux-testing-opaque-token-authorities"></a>Configuring Authorities</h3>
<div class="paragraph">
<p>In many circumstances, your method is protected by filter or method security and needs your <code>Authentication</code> to have certain granted authorities to allow the request.</p>
</div>
<div class="paragraph">
<p>In this case, you can supply what granted authorities you need using the <code>authorities()</code> method:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">client
    .mutateWith(mockOpaqueToken()
        .authorities(new SimpleGrantedAuthority("SCOPE_message:read"))
    )
    .get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">client
    .mutateWith(mockOpaqueToken()
        .authorities(SimpleGrantedAuthority("SCOPE_message:read"))
    )
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="webflux-testing-opaque-token-attributes"><a class="anchor" href="oauth2.html#webflux-testing-opaque-token-attributes"></a>Configuring Claims</h3>
<div class="paragraph">
<p>And while granted authorities are quite common across all of Spring Security, we also have attributes in the case of OAuth 2.0.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s say, for example, that you&#8217;ve got a <code>user_id</code> attribute that indicates the user&#8217;s id in your system.
You might access it like so in a controller:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">@GetMapping("/endpoint")
public Mono&lt;String&gt; foo(BearerTokenAuthentication authentication) {
    String userId = (String) authentication.getTokenAttributes().get("user_id");
    // ...
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">@GetMapping("/endpoint")
fun foo(authentication: BearerTokenAuthentication): Mono&lt;String?&gt; {
    val userId = authentication.tokenAttributes["user_id"] as String?
    // ...
}</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>In that case, you&#8217;d want to specify that attribute with the <code>attributes()</code> method:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">client
    .mutateWith(mockOpaqueToken()
        .attributes(attrs -&gt; attrs.put("user_id", "1234"))
    )
    .get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">client
    .mutateWith(mockOpaqueToken()
        .attributes { attrs -&gt; attrs["user_id"] = "1234" }
    )
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="webflux-testing-opaque-token-principal"><a class="anchor" href="oauth2.html#webflux-testing-opaque-token-principal"></a>Additional Configurations</h3>
<div class="paragraph">
<p>There are additional methods, too, for further configuring the authentication; it simply depends on what data your controller expects.</p>
</div>
<div class="paragraph">
<p>One such is <code>principal(OAuth2AuthenticatedPrincipal)</code>, which you can use to configure the complete <code>OAuth2AuthenticatedPrincipal</code> instance that underlies the <code>BearerTokenAuthentication</code></p>
</div>
<div class="paragraph">
<p>It&#8217;s handy if you:
1. Have your own implementation of <code>OAuth2AuthenticatedPrincipal</code>, or
2. Want to specify a different principal name</p>
</div>
<div class="paragraph">
<p>For example, let&#8217;s say that your authorization server sends the principal name in the <code>user_name</code> attribute instead of the <code>sub</code> attribute.
In that case, you can configure an <code>OAuth2AuthenticatedPrincipal</code> by hand:</p>
</div>
<div class="exampleblock">
<div class="content">
<div class="listingblock primary">
<div class="title">Java</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-java hljs" data-lang="java">Map&lt;String, Object&gt; attributes = Collections.singletonMap("user_name", "foo_user");
OAuth2AuthenticatedPrincipal principal = new DefaultOAuth2AuthenticatedPrincipal(
        (String) attributes.get("user_name"),
        attributes,
        AuthorityUtils.createAuthorityList("SCOPE_message:read"));

client
    .mutateWith(mockOpaqueToken().principal(principal))
    .get().uri("/endpoint").exchange();</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Kotlin</div>
<div class="content">
<pre class="highlightjs highlight"><code class="language-kotlin hljs" data-lang="kotlin">val attributes: Map&lt;String, Any&gt; = mapOf(Pair("user_name", "foo_user"))
val principal: OAuth2AuthenticatedPrincipal = DefaultOAuth2AuthenticatedPrincipal(
    attributes["user_name"] as String?,
    attributes,
    AuthorityUtils.createAuthorityList("SCOPE_message:read")
)

client
    .mutateWith(mockOpaqueToken().principal(principal))
    .get().uri("/endpoint").exchange()</code></pre>
</div>
</div>
</div>
</div>
<div class="paragraph">
<p>Note that as an alternative to using <code>mockOpaqueToken()</code> test support, you can also mock the <code>OpaqueTokenIntrospector</code> bean itself with a <code>@MockBean</code> annotation.</p>
</div>
</div>
</div>
</div>
<nav class="pagination">
<span class="prev"><a href="csrf.html">Testing CSRF</a></span>
<span class="next"><a href="../../configuration/webflux.html">WebFlux Security</a></span>
</nav>
</article>
</div>
</main>
</div>
<footer class="footer flex">
<div id="spring-links flex">
<img id="springlogo" src="../../../../_/img/spring-logo.svg" alt="Spring">
<p class="smallest antialiased">© <script>var d = new Date();
        document.write(d.getFullYear());</script> <a href="https://www.vmware.com/">VMware</a>, Inc. or its affiliates. <a href="https://www.vmware.com/help/legal.html">Terms of Use</a> • <a href="https://www.vmware.com/help/privacy.html" rel="noopener noreferrer">Privacy</a> • <a href="https://spring.io/trademarks">Trademark Guidelines</a> <span id="thank-you-mobile">• <a href="https://spring.io/thank-you">Thank you</a></span> • <a href="https://www.vmware.com/help/privacy/california-privacy-rights.html">Your California Privacy Rights</a> • <a class="ot-sdk-show-settings">Cookie Settings</a> <span id="teconsent"></span></p>
<p class="smallest antialiased">Apache®, Apache Tomcat®, Apache Kafka®, Apache Cassandra&trade;, and Apache Geode&trade; are trademarks or registered trademarks of the Apache Software Foundation in the United States and/or other countries. Java&trade;, Java&trade; SE, Java&trade; EE, and OpenJDK&trade; are trademarks of Oracle and/or its affiliates. Kubernetes® is a registered trademark of the Linux Foundation in the United States and other countries. Linux® is the registered trademark of Linus Torvalds in the United States and other countries. Windows® and Microsoft® Azure are registered trademarks of Microsoft Corporation. “AWS” and “Amazon Web Services” are trademarks or registered trademarks of Amazon.com Inc. or its affiliates. All other trademarks and copyrights are property of their respective owners and are only mentioned for informative purposes. Other names may be trademarks of their respective owners.</p>
</div>
<div id="social-icons" class="flex jc-between">
<a href="https://www.youtube.com/user/SpringSourceDev" title="Youtube"><svg id="youtube-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40"><circle class="cls-1" cx="20" cy="20" r="20" /><path class="cls-2" d="M30.91,14.53a2.89,2.89,0,0,0-2-2C27.12,12,20,12,20,12s-7.12,0-8.9.47a2.9,2.9,0,0,0-2,2A30.56,30.56,0,0,0,8.63,20a30.44,30.44,0,0,0,.46,5.47,2.89,2.89,0,0,0,2,2C12.9,28,20,28,20,28s7.12,0,8.9-.47a2.87,2.87,0,0,0,2-2A30.56,30.56,0,0,0,31.37,20,28.88,28.88,0,0,0,30.91,14.53ZM17.73,23.41V16.59L23.65,20Z" /></svg></a>
<a href="https://github.com/spring-projects" title="Github"><svg id="github-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 75.93 75.93"><path class="cls-1" d="M38,0a38,38,0,1,0,38,38A38,38,0,0,0,38,0Z" /></g><path class="cls-2" d="M38,15.59A22.95,22.95,0,0,0,30.71,60.3c1.15.21,1.57-.5,1.57-1.11s0-2,0-3.9c-6.38,1.39-7.73-3.07-7.73-3.07A6.09,6.09,0,0,0,22,48.86c-2.09-1.42.15-1.39.15-1.39a4.81,4.81,0,0,1,3.52,2.36c2,3.5,5.37,2.49,6.67,1.91a4.87,4.87,0,0,1,1.46-3.07c-5.09-.58-10.45-2.55-10.45-11.34a8.84,8.84,0,0,1,2.36-6.15,8.29,8.29,0,0,1,.23-6.07s1.92-.62,6.3,2.35a21.82,21.82,0,0,1,11.49,0c4.38-3,6.3-2.35,6.3-2.35a8.29,8.29,0,0,1,.23,6.07,8.84,8.84,0,0,1,2.36,6.15c0,8.81-5.37,10.75-10.48,11.32a5.46,5.46,0,0,1,1.56,4.25c0,3.07,0,5.54,0,6.29s.42,1.33,1.58,1.1A22.94,22.94,0,0,0,38,15.59Z" /></svg></a>
<a href="https://twitter.com/springcentral" title="Twitter"><svg id="twitter-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 75.93 75.93"><circle class="cls-1" cx="37.97" cy="37.97" r="37.97" /><path id="Twitter-2" data-name="Twitter" class="cls-2" d="M55.2,22.73a15.43,15.43,0,0,1-4.88,1.91,7.56,7.56,0,0,0-5.61-2.49A7.78,7.78,0,0,0,37,30a7.56,7.56,0,0,0,.2,1.79,21.63,21.63,0,0,1-15.84-8.23,8,8,0,0,0,2.37,10.52,7.66,7.66,0,0,1-3.48-1v.09A7.84,7.84,0,0,0,26.45,41a7.54,7.54,0,0,1-2,.28A7.64,7.64,0,0,1,23,41.09a7.71,7.71,0,0,0,7.18,5.47,15.21,15.21,0,0,1-9.55,3.37,15.78,15.78,0,0,1-1.83-.11,21.41,21.41,0,0,0,11.78,3.54c14.13,0,21.86-12,21.86-22.42,0-.34,0-.68,0-1a15.67,15.67,0,0,0,3.83-4.08,14.9,14.9,0,0,1-4.41,1.24A7.8,7.8,0,0,0,55.2,22.73Z" /></svg></a>
</div>
</footer>
<script src="../../../../_/js/site.js"></script>
<script async src="../../../../_/js/vendor/highlight.js"></script>
<script async src="../../../../_/js/vendor/tabs.js"></script>
<script src="../../../../_/js/vendor/switchtheme.js"></script>
<script src="../../../../_/js/vendor/docsearch.min.js"></script>

<script>
var search = docsearch({
  appId: '244V8V9FGG',
  apiKey: '82c7ead946afbac3cf98c32446154691',
  indexName: 'security-docs',
  inputSelector: '#search-input',
  autocompleteOptions: { hint: false, keyboardShortcuts: ['s'] },
  algoliaOptions: { hitsPerPage: 10 }
}).autocomplete
search.on('autocomplete:closed', function () { search.autocomplete.setVal() })
</script>
<script>if (window.parent == window) {(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','//www.google-analytics.com/analytics.js','ga');ga('create', 'UA-2728886-23', 'auto', {'siteSpeedSampleRate': 100});ga('send', 'pageview');}</script><script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"702e40090cc49830","token":"bffcb8a918ae4755926f76178bfbd26b","version":"2021.12.0","si":100}' crossorigin="anonymous"></script>
</body>
</html>
